package com.xbongbong.paas.elasticsearch.model.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.model.PaasFormSubDataEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.dto.AssociationListDataDTO;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.pojo.vo.FormDataRepeatBatchVO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.FormSubDataUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.BelongEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.PaasFormDataEsMappingDTO;
import com.xbongbong.paas.pojo.dto.UpdateByQueryDTO;
import com.xbongbong.paas.pojo.vo.AssociationListDataVO;
import com.xbongbong.paas.pojo.vo.DistributorMapVO;
import com.xbongbong.paas.pojo.vo.FormDataRepeatVO;
import com.xbongbong.paas.pojo.vo.LinkSearchListVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.MunicipalityEnum;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.FormDataVO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderDataEsListVO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.WorkOrderEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.DistributorEnum;
import com.xbongbong.saas.enums.business.OtherExpenseEnum;
import com.xbongbong.saas.enums.business.OtherIncomeEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.join.query.HasChildQueryBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.scriptQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;


/**
 * @author kaka
 * @time 2018-9-18 13:44
 */
@Service("paasFormDataEsModel")
public class PaasFormDataEsModelImpl implements PaasFormDataEsModel {

    /**
     * es至少有一个条件满足
     */
    private static final int MINI_MUM_SHOULD_MATCH = 1;

    private static final Logger LOG = LoggerFactory.getLogger(PaasFormDataEsModelImpl.class);

    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PaasFormSubDataEsModel paasFormSubDataEsModel;

    private String  index = IndexTypeEnum.IDX_FORM_DATA.getIndex();
    private String  type = IndexTypeEnum.IDX_FORM_DATA.getType();

    @Override
    public void insert(PaasFormDataEntity paasFormDataEntity) throws XbbException {
        try {
            IndexRequest indexRequest = getIndexRequest(paasFormDataEntity);
            RestHighLevelClient client = xbbElasticsearchRestTemplate.getRestHighLevelClient(index);
            client.index(indexRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            LOG.error("es插入报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void insert(PaasFormDataEntity paasFormDataEntity, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        try {
            IndexRequest indexRequest = getIndexRequest(paasFormDataEntity, refreshPolicy);
            RestHighLevelClient client = xbbElasticsearchRestTemplate.getRestHighLevelClient(index);
            client.index(indexRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            LOG.error("es插入报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private IndexRequest getIndexRequest(PaasFormDataEntity paasFormDataEntity, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        paasFormDataEntity.setEsId(paasFormDataEntity.getCorpid() + "_" + paasFormDataEntity.getId());
        paasFormDataEntity.setDataId(paasFormDataEntity.getId());
        paasFormDataEntity.setMy_join_field(type);
        IndexRequest indexRequest = new IndexRequest();
        indexRequest
                .index(index)
                .setRefreshPolicy(refreshPolicy)
                .source(BeanUtil.convertBean2Map(paasFormDataEntity,true,true))
                .id(paasFormDataEntity.getEsId())
        ;
        return indexRequest;
    }

    /**
     * Description: 生成es数据插入用请求 其中对source的数据用 @QueryIgnore 进行了过滤
     * @param paasFormDataEntity
     * @return org.elasticsearch.action.index.IndexRequest
     */
    private IndexRequest getIndexRequest(PaasFormDataEntity paasFormDataEntity) throws XbbException {
        paasFormDataEntity.setEsId(paasFormDataEntity.getCorpid() + "_" + paasFormDataEntity.getId());
        paasFormDataEntity.setDataId(paasFormDataEntity.getId());
        paasFormDataEntity.setMy_join_field(type);
        IndexRequest indexRequest = new IndexRequest();
        indexRequest
                .index(index)
                .setRefreshPolicy(WriteRequest.RefreshPolicy.NONE)
                .source(BeanUtil.convertBean2Map(paasFormDataEntity,true,true))
                .id(paasFormDataEntity.getEsId())
        ;
        return indexRequest;
    }

    @Override
    public void insertBatch(List<PaasFormDataEntity> paasFormDataEntityList ) throws XbbException {
        if(CollectionsUtil.isEmpty(paasFormDataEntityList)){
            return;
        }
        try {
            BulkRequest bulkRequest = new BulkRequest();
            for (PaasFormDataEntity entity : paasFormDataEntityList) {
                IndexRequest indexRequest = getIndexRequest(entity);
                bulkRequest.add(indexRequest);
            }
            bulk(bulkRequest,index);
        } catch (Exception e) {
            LOG.error("es批量插入报错",e);
            throw  new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void update(PaasFormDataEntity paasFormDataEntity) throws XbbException {
        try {
            //处理数据
            paasFormDataEntity.setEsId(paasFormDataEntity.getCorpid() + "_" + paasFormDataEntity.getId());
            paasFormDataEntity.setDataId(paasFormDataEntity.getId());
            //fix 50369 编辑进审批导致创建人被更新了
            paasFormDataEntity.setCreatorId(null);
            //塞入要更新的内容
            UpdateRequest updateRequest = new UpdateRequest();
            updateRequest.doc(BeanUtil.convertBean2Map(paasFormDataEntity,true,true))
                    .index(index)
                    .id(paasFormDataEntity.getEsId())
            ;
            update(updateRequest);
        } catch (Exception e) {
            LOG.error("es更新报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private void update(UpdateRequest updateRequest) throws IOException, XbbException {
        RestHighLevelClient client = xbbElasticsearchRestTemplate.getRestHighLevelClient(index);
        updateRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.NONE).retryOnConflict(5);
        client.update(updateRequest, RequestOptions.DEFAULT);
    }

    @Override
    public void updateBatch(List<UpdateDataEntity> jsonArray) throws XbbException {
        try {
            if(CollectionsUtil.isEmpty(jsonArray)){
                return;
            }

            List<InsertDTO> insertList = new ArrayList<>();
            for (UpdateDataEntity updateDataEntity : jsonArray) {
                InsertDTO insertDTO = paasEsModel.getInsertDTOForUpdateEntity(updateDataEntity, IndexTypeEnum.IDX_FORM_DATA);
                insertList.add(insertDTO);
            }
            paasEsModel.updateBatch(insertList);
        } catch (Exception e) {
            LOG.error("es更新报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void updateBatch(List<UpdateDataEntity> list, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        try {
            if(CollectionsUtil.isEmpty(list)){
                return;
            }

            List<InsertDTO> insertList = new ArrayList<>();
            for (UpdateDataEntity updateDataEntity : list) {
                InsertDTO insertDTO = paasEsModel.getInsertDTOForUpdateEntity(updateDataEntity, IndexTypeEnum.IDX_FORM_DATA);
                insertList.add(insertDTO);
            }
            paasEsModel.updateBatch(insertList, refreshPolicy);
        } catch (Exception e) {
            LOG.error("es更新报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void delete(Long key,String corpid) throws IOException, XbbException {
        //塞入要更新的内容
        UpdateRequest updateRequest = new UpdateRequest();
        Map<String, Object> map = new HashMap<>(16);
        map.put("del",1);
        updateRequest.doc(map)
                .index(index)
                .id(corpid + "_" + key);
        update(updateRequest);
    }
    @Override
    public void updateBatch(List<Long> list, String corpid, Map<String,Object> map) throws XbbException {
        updateBatch(list, corpid, map,IndexTypeEnum.IDX_FORM_DATA);
    }

    /**
     * 获取BulkRequest
     * @return
     */
    private BulkRequest getBulkRequest() {
        BulkRequest bulkRequest = Requests.bulkRequest();
        //等待可见
        bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
        return bulkRequest;
    }

    /**
     *Executes a bulk of index / delete operations.
     * @param bulkRequest
     * @throws XbbException
     */
    private void bulk(BulkRequest bulkRequest,String indexName) throws XbbException {
        RestHighLevelClient client = xbbElasticsearchRestTemplate.getRestHighLevelClient(indexName);
        try {
            client.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            LOG.error("es报错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public Long count(SearchRequest searchRequest) throws XbbException {
        long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
        return count;
    }

    @Override
    public FormDataRepeatVO repeat(PageRequest pageRequest, SearchRequest searchRequest) throws XbbException {
        FormDataRepeatVO formDataRepeatVO = new FormDataRepeatVO();
        try {
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPagesWithoutCount(pageRequest,searchRequest, PaasFormDataEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<PaasFormDataEntityExt> resultList = esEntities.getContent();
            formDataRepeatVO.setFormDataList(resultList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataRepeatVO;
    }

    @Override
    public FormDataRepeatBatchVO repeatBatch(PageRequest pageRequest, SearchRequest searchRequest) throws XbbException {
        FormDataRepeatBatchVO formDataRepeatBatchVO = new FormDataRepeatBatchVO();
        try {
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPagesWithoutCount(pageRequest,searchRequest, PaasFormDataEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<PaasFormDataEntityExt> resultList = esEntities.getContent();
            formDataRepeatBatchVO.setFormDataList(resultList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataRepeatBatchVO;
    }




    @Override
    public void updateByQuery(UpdateByQueryDTO updateByQueryDTO) throws XbbException {
        try {
           /* UpdateByQueryRequestBuilder updateByQuery = getUpdateByQueryRequestBuilder();
            //
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            //TODO   通用更新操作的查询（此处可以改为处理不同的查询条件）
            boolQueryBuilder.filter(termQuery("corpid.keyword", updateByQueryDTO.getCorpid()))
                    .filter(termsQuery("dataId", updateByQueryDTO.getIdList()));
            updateData(updateByQueryDTO, updateByQuery, boolQueryBuilder);*/
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public PaasFormDataEsListVO list(FormDataListDTO formDataListDTO, IndexTypeEnum indexTypeEnum) throws XbbException {
        PaasFormDataEsListVO formDataListVO = new PaasFormDataEsListVO();
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            SearchRequest searchRequest = getSearchRequest(formDataListDTO, indexTypeEnum, sourceBuilder);
            if (Objects.equals(formDataListDTO.getIsDistributorMap(), 1)) {
                formDataListVO.setDistributorAddress(formDataListDTO.getDistributorAddress());
                return distributorMap(formDataListDTO, formDataListVO, searchRequest, indexTypeEnum, sourceBuilder);
            }
            String prefix = "------------------listByEs------------------:";
            StringBuilder syso = setStringBuilder4Log(indexTypeEnum, prefix);
            LOG.info(syso.toString());
            long num;
            List<PaasFormDataEntityExt> resultList;
            //分页
            PageRequest  pageRequest= EsUtil.setPage(sourceBuilder, formDataListDTO.getPage(), formDataListDTO.getPageSize());

            Object[] sortValue = new Object[]{};
            if (Objects.equals(formDataListDTO.getFromExport(), 1)) {
                resultList = xbbElasticsearchRestTemplate.getScrollListForExport(PaasFormDataEntityExt.class, searchRequest);
                num = resultList.size();
            } else {
                XbbAggregatedPage<PaasFormDataEntityExt> xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
                resultList = xbbAggregatedPage.getContent();
                num =  xbbAggregatedPage.getTotalElements();
                sortValue = xbbAggregatedPage.getSortValue();
            }
            //
            Set<Long> parentIdList = new HashSet<>();
            for (PaasFormDataEntityExt paasFormDataEntityExt : resultList) {
                paasFormDataEntityExt.setTagData(new JSONObject());
                parentIdList.add(paasFormDataEntityExt.getDataId());
            }
            // 判断是否需要增加子表单数据
            if (Objects.nonNull(formDataListDTO.getSearchSubForm()) && formDataListDTO.getSearchSubForm()) {
                // 查询子表单数据
                List<String> subFieldList = formDataListDTO.getSubFieldList();
                Integer subPageSize = parentIdList.size() * 500;
                indexTypeEnum = IndexTypeEnum.getSubEnum(indexTypeEnum);
                List<PaasFormSubDataEntity> paasFormSubDataList = paasFormSubDataEsModel.getSubDataByParentId(formDataListDTO.getCorpid(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), subFieldList, formDataListDTO.getFormId(), parentIdList, 1, subPageSize, indexTypeEnum);
                // 封装子表单数据进主表数据
                FormSubDataUtil.setSubData(resultList, paasFormSubDataList);
            }

            PageHelper pageHelper = new PageHelper(formDataListDTO.getPage(), formDataListDTO.getPageSize());
            pageHelper.setRowsCount((int) num);
            formDataListVO.setPaasFormDataESList(resultList);
            formDataListVO.setPageHelper(pageHelper);
            formDataListVO.setBusinessType(formDataListDTO.getBusinessType());
            if (Objects.equals(2, formDataListDTO.getFromExport())) {
                formDataListVO.setSortValue(sortValue);
            }
        } catch (XbbException e) {
            LOG.error("es查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        } catch (Exception e) {
            LOG.error("es查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataListVO;
    }

    private PaasFormDataEsListVO distributorMap(FormDataListDTO formDataListDTO, PaasFormDataEsListVO formDataListVO, SearchRequest searchRequest, IndexTypeEnum indexTypeEnum, SearchSourceBuilder sourceBuilder) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) searchRequest.source().query();
        String provinceAttr = CustomerManagementEnum.getAddress4Aggs(CustomerManagementEnum.ADDRESS, "province");
        String cityAttr = CustomerManagementEnum.getAddress4Aggs(CustomerManagementEnum.ADDRESS, "city");
        String districtAttr = CustomerManagementEnum.getAddress4Aggs(CustomerManagementEnum.ADDRESS, "district");
        TermsAggregationBuilder termsAggregationBuilder;
        if (Objects.isNull(formDataListDTO.getDistributorMapVO()) || Objects.isNull(formDataListDTO.getDistributorMapVO().getProvince())) {
            termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(provinceAttr);
        } else if (Objects.nonNull(formDataListDTO.getDistributorMapVO().getDistrict())) {
            //分页
            PageRequest  pageRequest= EsUtil.setPage(sourceBuilder, formDataListDTO.getPage(), 200);
            XbbAggregatedPage<PaasFormDataEntityExt> xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
            List<PaasFormDataEntityExt> resultList = xbbAggregatedPage.getContent();
            List<DistributorMapVO> distributorMapVOList = new ArrayList<>();
            Map<String, Integer> lonAndLatMap = new HashMap<>();
            for (PaasFormDataEntityExt paasFormDataEntityExt : resultList) {
                JSONObject address = paasFormDataEntityExt.getData().getJSONObject(DistributorEnum.ADDRESS.getAttr());
                if (address != null && address.containsKey("location")) {
                    String province = address.getString("province");
                    String city = address.getString("city");
                    String district = address.getString("district");
                    String addressString = address.getString("address");
                    JSONObject location = address.getJSONObject("location");
                    // 散点图数据
                    DistributorMapVO scatterData = new DistributorMapVO();
                    if (Objects.nonNull(formDataListDTO.getDistributorMapVO())) {
                        BeanUtil.copyProperties(formDataListDTO.getDistributorMapVO(), scatterData, true);
                    }
                    scatterData.setName(province + city + district + addressString);
                    scatterData.setDataId(paasFormDataEntityExt.getDataId());
                    scatterData.setDistributorName(paasFormDataEntityExt.getData().getString(DistributorEnum.NAME.getAttr()));
                    // 经纬度
                    Double lon = location.getDouble("lon");
                    Double lat = location.getDouble("lat");
                    if (Objects.isNull(lon) || Objects.isNull(lat)) {
                        continue;
                    }
                    scatterData.setLongitude(lon);
                    scatterData.setLatitude(lat);
                    // 返回时根据经纬度分组
                    boolean noAdd = true;
                    StringJoiner sj = new StringJoiner(",");
                    sj.add(scatterData.getLongitude().toString());
                    sj.add(scatterData.getLatitude().toString());
                    // 已有分组就添加进去
                    if (lonAndLatMap.containsKey(sj.toString())) {
                        noAdd = false;
                        distributorMapVOList.get(lonAndLatMap.get(sj.toString())).getScatterData().add(scatterData);
                    }
                    // 没分组创建一个分组
                    if (noAdd) {
                        List<DistributorMapVO> scatterDataList = new ArrayList<>();
                        scatterDataList.add(scatterData);
                        // 初始化vo,这里外层VO只存经纬度,数据放在内层scatterData中
                        DistributorMapVO distributorMapVO = new DistributorMapVO();
                        distributorMapVO.setLatitude(scatterData.getLatitude());
                        distributorMapVO.setLongitude(scatterData.getLongitude());
                        distributorMapVO.setScatterData(scatterDataList);
                        // 以下三个属性前端不需要，为避免以后理解混乱，先不返回
                        distributorMapVO.setDistributorMark(null);
                        distributorMapVO.setSaasMark(null);
                        distributorMapVO.setBusinessType(null);
                        distributorMapVOList.add(distributorMapVO);
                        // 把经纬度拼接成字符串，存入map中，key经纬度，value为distributorMapVOList下标
                        StringJoiner newSj = new StringJoiner(",");
                        newSj.add(scatterData.getLongitude().toString());
                        newSj.add(scatterData.getLatitude().toString());
                        lonAndLatMap.put(newSj.toString(), distributorMapVOList.size() - 1);
                    }
                }
            }
            formDataListVO.setDistributorMapVOList(distributorMapVOList);
            return formDataListVO;
        } else if (Objects.nonNull(formDataListDTO.getDistributorMapVO().getCity())) {
            termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(districtAttr);
        } else if (Objects.nonNull(formDataListDTO.getDistributorMapVO().getProvince())
                && MunicipalityEnum.isExist(formDataListDTO.getDistributorMapVO().getProvince())) { // 直辖市特殊处理
            termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(districtAttr);
        } else {
            termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(cityAttr);
        }
        //该桶要置为最大
        termsAggregationBuilder.size(Integer.MAX_VALUE);
        termsAggregationBuilder.executionHint(ElasticConstant.EXECUTION_HINT);
        JSONObject resultJsonObject = esHelper.elasticAggs4Buckets2Object(indexTypeEnum, boolQueryBuilder, termsAggregationBuilder);
        JSONArray bucketsArray = resultJsonObject.getJSONArray("buckets");
        List<DistributorMapVO> distributorMapVOList = new ArrayList<>();
        for (Object object : bucketsArray) {
            if (object != null) {
                JSONObject dataJsonObject = (JSONObject) object;
                //该key为省或市的名称
                String name = dataJsonObject.getString("key");
                if (!StringUtil.isEmpty(name)) {
                    DistributorMapVO distributorMapVO = new DistributorMapVO();
                    if (Objects.nonNull(formDataListDTO.getDistributorMapVO())) {
                        BeanUtil.copyProperties(formDataListDTO.getDistributorMapVO(), distributorMapVO, true);
                    }
                    distributorMapVO.setName(name);
                    // 直辖市特殊处理
                    if (Objects.nonNull(formDataListDTO.getDistributorMapVO().getProvince())
                            && MunicipalityEnum.isExist(formDataListDTO.getDistributorMapVO().getProvince())) {
                        distributorMapVO.setCity(distributorMapVO.getProvince());
                    }
                    //没有选省市区的不画
                    String value = dataJsonObject.getString("doc_count");
                    distributorMapVO.setNum(value);
                    distributorMapVOList.add(distributorMapVO);
                }
            }
        }
        formDataListVO.setDistributorMapVOList(distributorMapVOList);
        return formDataListVO;
    }

    @Override
    public SearchRequest getSearchRequest(FormDataListDTO formDataListDTO, IndexTypeEnum indexTypeEnum, SearchSourceBuilder sourceBuilder) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        return getSearchRequest(formDataListDTO, indexTypeEnum, sourceBuilder, boolQueryBuilder);
    }
    @Override
    public SearchRequest getSearchRequest(FormDataListDTO formDataListDTO, IndexTypeEnum indexTypeEnum, SearchSourceBuilder sourceBuilder, BoolQueryBuilder boolQueryBuilder) throws XbbException {
        if (Objects.nonNull(formDataListDTO.getLegacyDataFlag()) && formDataListDTO.getLegacyDataFlag() && Objects.nonNull(formDataListDTO.getStageProcessId())) {
            BoolQueryBuilder stageProcessQuery = boolQuery();
            BoolQueryBuilder query = boolQuery();
            Long stageProcessId = formDataListDTO.getStageProcessId();
            query.filter(termsQuery("data.long_1", Collections.singletonList(stageProcessId)));
            BoolQueryBuilder mustNot = boolQuery();
            mustNot.mustNot(existsQuery("data.long_1"));
            stageProcessQuery.should(query);
            stageProcessQuery.should(mustNot);
            boolQueryBuilder.filter(stageProcessQuery);
        } else if (Objects.nonNull(formDataListDTO.getStageProcessId())) {
            boolQueryBuilder.filter(termsQuery("data.long_1", Collections.singletonList(formDataListDTO.getStageProcessId())));
        }
        //解析查询条件
        EsUtil.parseCondition(boolQueryBuilder,formDataListDTO.getConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
        // 拼接corpid，formId，del数据
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT+ StringConstant.KEY_WORD, formDataListDTO.getCorpid()));
        if (Objects.nonNull(formDataListDTO.getFormId()) && !Objects.equals(formDataListDTO.getFormId(), 0L)) {
            boolQueryBuilder.filter(termQuery(StringConstant.FORM_ID, formDataListDTO.getFormId()));
        }
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, formDataListDTO.getDel()));
        if (formDataListDTO.getLimitForms()){
            esHelper.removeSearchCondition(boolQueryBuilder, "formId");
            boolQueryBuilder.filter(termsQuery("formId",formDataListDTO.getFormIdList()));
        }
        //解析或条件
        EsUtil.parseShouldCondition(boolQueryBuilder,formDataListDTO.getShouldConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
        // 解析库存查询条件
        EsUtil.parseProductSearchCondition(boolQueryBuilder,formDataListDTO.getProductSerchConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getSubBusinessType());
        // 解析共享权限
        EsUtil.parseSharePermissionCondition(boolQueryBuilder, formDataListDTO.getSharePermission(), formDataListDTO.getCorpid(), formDataListDTO.getBusinessType(), formDataListDTO.getFromThrough());
        // 库存预警筛选仓库，筛选出已关联仓库的数据,拼接查询条件
        List<Long> includeIds = formDataListDTO.getIncludeIds();
        if (CollectionsUtil.isNotEmpty(includeIds)){
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),includeIds));
        }
        // 空数组没有数据
        if (Objects.nonNull(includeIds) && includeIds.size() == 0){
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), Arrays.asList(-1)));
        }
        esHelper.removeSearchCondition(boolQueryBuilder, "includeIds");
        sourceBuilder.query(boolQueryBuilder);
        if (Objects.equals(2, formDataListDTO.getFromExport()) && Objects.nonNull(formDataListDTO.getSearchAfterList()) && formDataListDTO.getSearchAfterList().length>0) {
            // 导出数据的游标
            sourceBuilder.searchAfter(formDataListDTO.getSearchAfterList());
        }
        //排序
        SortOrder order = SortOrder.DESC;
        String sortField = "updateTime";
        Map<String, String> sortMap = formDataListDTO.getSortMap();
        boolean hasStageSortField = false;
        String stageCodeField = "";
        if(sortMap != null && !sortMap.isEmpty()){
            sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
            Map<String, FieldAttrEntity> explainMap = formDataListDTO.getExplainMap();
            if(explainMap.containsKey(sortField)){
                String raw = ".raw";
                FieldAttrEntity sortFieldEntity = explainMap.get(sortField);
                FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(sortFieldEntity.getFieldType());
                if(FieldTypeEnum.TEXT.getEsalias().equals( fieldTypeEnum.getEsalias())){
                    if (Objects.equals(fieldTypeEnum, FieldTypeEnum.STAGE_THRUSTER)) {
                        stageCodeField = "data." +  sortField + raw;
                        sortField = PaasStageEnum.STAGE_ID.getAttr();
                        hasStageSortField = true;
                    } else {
                        sortField = sortField + raw;
                    }
                }

                //两个阶段停留时长字段的列表页排序和ES排序 是相反的（业务上的特殊逻辑）
                if (Objects.equals(sortFieldEntity.getFieldType(), FieldTypeEnum.FIRST_INTO_STAGE_TIME.getType())
                        || Objects.equals(sortFieldEntity.getFieldType(), FieldTypeEnum.NOW_INTO_STAGE_TIME.getType())) {
                    handleStageStayTimeSort(sortMap);
                }

                //预收款余额列表都不要加data.
                if(!Objects.equals(XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(),formDataListDTO.getBusinessType()) && !Objects.equals(XbbRefTypeEnum.PREPAY_BALANCE.getCode(),formDataListDTO.getBusinessType())){
                    //系统字段不用加data.
                    if (!BelongEnum.SYSTEM.getAlias().equals(fieldTypeEnum.getBelong())) {
                        sortField = "data." + sortField;
                    } else if (Objects.equals(fieldTypeEnum.getType(), FieldTypeEnum.SERIALNO.getType()) && !sortField.contains(fieldTypeEnum.getAlias())) {
                        sortField = "data." + sortField;
                    }
                }
            } else {
                // 排序不存在字段列表中时，给定默认排序，以防报错
                sortField = "updateTime";
            }
            if(SortOrder.ASC.toString().equals(sortMap.get("sort"))){
                order = SortOrder.ASC;
            }
        }
        sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));
        if (hasStageSortField) {
            sourceBuilder.sort(new FieldSortBuilder(stageCodeField).order(order));
        }
        sourceBuilder.sort(new FieldSortBuilder("id").order(order));

        //saas模糊查询
        if (Objects.equals(formDataListDTO.getBusinessType(),XbbRefTypeEnum.PRODUCT.getCode()) && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.STOCK_SEARCH.getCode())
            && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WARNING_SEARCH.getCode()) && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.GUARANTEE_SEARCH.getCode())){
            boolean onlyNameLike = formDataListDTO.getShouldConditions().isEmpty() && formDataListDTO.getProductSerchConditions().isEmpty();
            EsUtil.setProductNameLike(formDataListDTO.getNameLike(),formDataListDTO.getNameLikeIdIn(),boolQueryBuilder,onlyNameLike);
        }else {
            boolean onlyOneShould = formDataListDTO.getShouldConditions().isEmpty();
            if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.STOCK_SEARCH.getCode())) {
                onlyOneShould = false;
            }
            EsUtil.setNameLike(formDataListDTO.getSaasMark(),formDataListDTO.getNameLike(),formDataListDTO.getBusinessType(),formDataListDTO.getSimple(),boolQueryBuilder,onlyOneShould,formDataListDTO.getExplainMap(), formDataListDTO.getLoginUser());
        }
        // es脚本设置
        if (formDataListDTO.getEsScriptPojo() != null) {
            EsUtil.parseEsScript(formDataListDTO.getEsScriptPojo(), boolQueryBuilder);
        }
        // es 脚本处理
        if (formDataListDTO.getEsScriptSourceStr() != null) {
            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
            Script script = new Script(formDataListDTO.getEsScriptSourceStr());
            innerBoolQueryBuilder.filter(scriptQuery(script));
            boolQueryBuilder.filter(innerBoolQueryBuilder);
        }
        //限定连接值
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));

        HasChildQueryBuilder hasChildQueryBuilder = EsUtil.teamQueryBuilder(formDataListDTO);
        if (Objects.nonNull(hasChildQueryBuilder)) {
            boolQueryBuilder.filter(hasChildQueryBuilder);
        }

        //限定返回值
        List<String> fieldList = formDataListDTO.getFieldList();
        EsUtil.setFieldList(sourceBuilder, fieldList);
        //设置查询路由
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        searchRequest.source(sourceBuilder);
        return searchRequest;
    }

    /**
     * 阶段停留时长字段排序 取反
     * @param sortMap
     */
    private void handleStageStayTimeSort(Map<String, String> sortMap) {
        if (Objects.equals(SortOrder.ASC.toString(), sortMap.get("sort"))) {
            sortMap.put("sort", SortOrder.DESC.toString());
        } else if (Objects.equals(SortOrder.DESC.toString(), sortMap.get("sort"))) {
            sortMap.put("sort", SortOrder.ASC.toString());
        }
    }

    @Override
    public WorkOrderDataEsListVO workOrderList(FormDataListDTO formDataListDTO) throws XbbException {
        WorkOrderDataEsListVO workOrderDataEsListVO = new WorkOrderDataEsListVO();
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(boolQueryBuilder,formDataListDTO.getConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
            // 拼接appId，菜单id等数据
            EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
            //解析或条件
            EsUtil.parseShouldCondition(boolQueryBuilder,formDataListDTO.getShouldConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
            List<Long> formIdList = formDataListDTO.getFormIdList();
            if (formIdList != null && formIdList.size() != 0) {
                boolQueryBuilder.filter(termsQuery("formId", formIdList));
            }
            //排序
            SortOrder order = SortOrder.DESC;
            String sortField = "updateTime";
            Map<String, String> sortMap = formDataListDTO.getSortMap();
            if(sortMap != null && !sortMap.isEmpty()){
                sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
                Map<String, FieldAttrEntity> explainMap = formDataListDTO.getExplainMap();
                if(explainMap.containsKey(sortField)){
                    String raw = ".raw";
                    FieldAttrEntity sortFieldEntity = explainMap.get(sortField);
                    FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(sortFieldEntity.getFieldType());
                    if(FieldTypeEnum.TEXT.getEsalias().equals( fieldTypeEnum.getEsalias())){
                        sortField = sortField + raw;
                    }
                    //系统字段不用加data.
                    if (!BelongEnum.SYSTEM.getAlias().equals(fieldTypeEnum.getBelong())) {
                        sortField = "data." + sortField;
                    }else if (Objects.equals(fieldTypeEnum.getType(),FieldTypeEnum.SERIALNO.getType()) && !sortField.contains(fieldTypeEnum.getAlias())){
                        sortField = "data." + sortField;
                    }
                }
                if(SortOrder.ASC.toString().equals(sortMap.get("sort"))){
                    order = SortOrder.ASC;
                }
            }
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));

            HasChildQueryBuilder hasChildQueryBuilder = EsUtil.teamQueryBuilder(formDataListDTO);
            if (Objects.nonNull(hasChildQueryBuilder)) {
                boolQueryBuilder.filter(hasChildQueryBuilder);
            }

            //saas模糊查询
            boolean onlyNameLike = formDataListDTO.getShouldConditions().isEmpty();
            EsUtil.setNameLike(formDataListDTO.getSaasMark(),formDataListDTO.getNameLike(),formDataListDTO.getBusinessType(),formDataListDTO.getSimple(),boolQueryBuilder,onlyNameLike,formDataListDTO.getExplainMap(), null);
            // es脚本设置
            if (formDataListDTO.getEsScriptPojo() != null) {
                EsUtil.parseEsScript(formDataListDTO.getEsScriptPojo(), boolQueryBuilder);
            }
            //分页
            Integer page = formDataListDTO.getPage();
            Integer pageSize = formDataListDTO.getPageSize();
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            //设置查询路由
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_WORK_ORDER;
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<WorkOrderEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, WorkOrderEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<WorkOrderEntityExt> resultList = esEntities.getContent();
            //
            Set<Long> parentIdList = new HashSet<>();
            for (WorkOrderEntityExt entity : resultList) {
                entity.setTagData(new JSONObject());
                parentIdList.add(entity.getDataId());
            }
            // 判断是否需要增加子表单数据
            if (Objects.nonNull(formDataListDTO.getSearchSubForm()) && formDataListDTO.getSearchSubForm()) {
                // 查询子表单数据
                List<String> subFieldList = formDataListDTO.getSubFieldList();
                indexTypeEnum = EsUtil.getSubFormIndexTypeEnum(indexTypeEnum);
                List<PaasFormSubDataEntity> paasFormSubDataList = paasFormSubDataEsModel.getSubDataByParentId(formDataListDTO.getCorpid(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), subFieldList, formDataListDTO.getFormId(), parentIdList, null, null, indexTypeEnum);
                // 封装子表单数据进主表数据
                FormSubDataUtil.setSubData(resultList, paasFormSubDataList);
            }
            long num = esEntities.getTotalElements();
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) num);
            workOrderDataEsListVO.setPaasFormDataESList(resultList);
            workOrderDataEsListVO.setPageHelper(pageHelper);
        } catch (XbbException e) {
            LOG.error("es查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return workOrderDataEsListVO;
    }

    /**
     * 解析或条件
     * @param boolQueryBuilder
     * @param formDataListDTO
     */
//    private void parseShouldCondition(BoolQueryBuilder boolQueryBuilder, FormDataListDTO formDataListDTO) throws XbbException{
//        List<List<ConditionsEntityExt>> publicGroupConditions = formDataListDTO.getShouldConditions();
//        if (publicGroupConditions == null || publicGroupConditions.isEmpty()){
//            return;
//        }
//        for (List<ConditionsEntityExt> conditionsEntityExtList : publicGroupConditions){
//            BoolQueryBuilder innerBoolQueryBuilder = boolQuery();
//            EsUtil.parseCondition(innerBoolQueryBuilder,conditionsEntityExtList,formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
//            boolQueryBuilder.should(innerBoolQueryBuilder);
//        }
//        boolQueryBuilder.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
//    }

    /**
     * 模糊查询参数设置
     * @author haibin.zhang
     */
//    private void setNameLike(FormDataListDTO formDataListDTO, BoolQueryBuilder boolQueryBuilder) {
//        if (!Objects.equals(formDataListDTO.getSaasMark(),SaasMarkEnum.SAAS.getCode())) {
//            return;
//        }
//        String nameLike = formDataListDTO.getNameLike();
//        if (nameLike == null || nameLike.isEmpty()) {
//            return;
//        }
//        List<String> searchAttrList = ListSearchEnum.getByBusinessType(formDataListDTO.getBusinessType(),formDataListDTO.getSimple());
//        for (String attr : searchAttrList){
//            boolQueryBuilder.should(matchPhraseQuery(attr, nameLike));
//        }
//        boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
//    }

    @Override
    public LinkSearchListVO filterLinkSearch(PageRequest pageRequest, SearchRequest searchRequest, Integer page, Integer pageSize) throws XbbException {
        LinkSearchListVO linkSearchListVO = new LinkSearchListVO();
        try {
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages( pageRequest,  searchRequest, PaasFormDataEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<PaasFormDataEntityExt> resultList = esEntities.getContent();
            long num = esEntities.getTotalElements();
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) num);
            List<FormDataVO> formDataList = new ArrayList<>();
            resultList.forEach((item)->{
                FormDataVO formDataVO = new FormDataVO();
                BeanUtil.copyProperties(item, formDataVO);
                formDataList.add(formDataVO);
            });
            linkSearchListVO.setPaasFormDataESList(formDataList);
            linkSearchListVO.setPageHelper(pageHelper);
        }catch (Exception e) {
            LOG.error("es关联查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return linkSearchListVO;
    }



    @Override
    public AssociationListDataVO associationListDataList(AssociationListDataDTO associationListDataDTO, IndexTypeEnum indexTypeEnum) throws XbbException {
        AssociationListDataVO associationListDataVO = new AssociationListDataVO();
        try {
            Integer page = associationListDataDTO.getPage();
            Integer pageSize = associationListDataDTO.getPageSize();

            //分页
            SearchSourceBuilder sourceBuilder = associationListDataDTO.getSourceBuilder();
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            //限定返回值
            List<String> fieldList = associationListDataDTO.getFieldList();
            EsUtil.setFieldList(sourceBuilder, fieldList);
            // 索引
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<WorkOrderEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, WorkOrderEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<WorkOrderEntityExt> resultList = esEntities.getContent();
            associationListDataVO.setResultList(resultList);
            long num = esEntities.getTotalElements();
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) num);
            associationListDataVO.setPageHelper(pageHelper);
        }catch (Exception e) {
            LOG.error("es关联查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return associationListDataVO;
    }

    @Override
    public void updateBatch(List<Long> dataIdList, String corpid, Map<String, Object> map, IndexTypeEnum indexTypeEnum) throws XbbException {
        if (CollectionsUtil.isEmpty(dataIdList)) {
            return;
        }
        try {
            BulkRequest bulkRequest = getBulkRequest();
            for (Long id : dataIdList) {
                String esId = corpid + "_" + id;
                //塞入要更新的内容
                UpdateRequest updateRequest = getUpdateRequest(map, esId, indexTypeEnum.getIndex(), indexTypeEnum.getType());
                bulkRequest.add(updateRequest);
            }
            bulk(bulkRequest,index);
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200019.getMsg(),e);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200019);
        }
    }

    private UpdateRequest getUpdateRequest(Map<String, Object> map, String esId, String index, String type) {
        UpdateRequest updateRequest = new UpdateRequest();
        map.put(ElasticConstant.MY_JOIN_FIELD,type);
        updateRequest.doc(map)
                .index(index)
                .id(esId)
                .retryOnConflict(5)
        ;
        return updateRequest;
    }


    private StringBuilder setStringBuilder4Log(IndexTypeEnum indexTypeEnum, String prefix) {
        StringBuilder syso = new StringBuilder();
        syso.append(prefix);
        syso.append("ProBaseConfig.getEsName():");
        syso.append(ProBaseConfig.getEsName());
        syso.append("indexTypeEnum:");
        syso.append(indexTypeEnum);
        syso.append(" index:");
        syso.append(indexTypeEnum.getIndex());
        syso.append(" type:");
        syso.append(indexTypeEnum.getType());
        return syso;
    }

    @Override
    public PaasFormDataEsListVO sheetList(FormDataListDTO formDataListDTO, IndexTypeEnum indexTypeEnum) throws XbbException {
        PaasFormDataEsListVO paasFormDataEsListVO = new PaasFormDataEsListVO();
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            //解析查询条件
            EsUtil.parseCondition(boolQueryBuilder,formDataListDTO.getConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
            // 拼接appId，菜单id等数据
            EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
            //解析或条件
            EsUtil.parseShouldCondition(boolQueryBuilder,formDataListDTO.getShouldConditions(),formDataListDTO.getRel(),formDataListDTO.getCorpid(),formDataListDTO.getBusinessType());
            // 解析共享权限
            EsUtil.parseSharePermissionCondition(boolQueryBuilder, formDataListDTO.getSharePermission(), formDataListDTO.getCorpid(), formDataListDTO.getBusinessType(), formDataListDTO.getFromThrough());

            List<Long> formIdList = formDataListDTO.getFormIdList();
            if (formIdList != null && formIdList.size() != 0) {
                boolQueryBuilder.filter(termsQuery("formId", formIdList));
            }
            //排序
            SortOrder order = SortOrder.DESC;
            switch (indexTypeEnum) {
                case IDX_SAAS_PAYPLAN_SHEET:
                    sourceBuilder.sort(new FieldSortBuilder("data."+ PaySheetEnum.REAL_PAY_TIME.getAttr()).order(order)).sort(new FieldSortBuilder(StringConstant.ADD_TIME).order(order));
                    break;
                case IDX_SAAS_OTHER_INCOME:
                    sourceBuilder.sort(new FieldSortBuilder("data."+ OtherIncomeEnum.INCOME_TIME.getAttr()).order(order)).sort(new FieldSortBuilder(StringConstant.ADD_TIME).order(order));
                    break;
                case IDX_SAAS_OTHER_EXPENSE:
                    sourceBuilder.sort(new FieldSortBuilder("data."+ OtherExpenseEnum.EXPENSE_TIME.getAttr()).order(order)).sort(new FieldSortBuilder(StringConstant.ADD_TIME).order(order));
                    break;
                default:
                    sourceBuilder.sort(new FieldSortBuilder("data."+ PaymentSheetEnum.PAYMENT_TIME.getAttr()).order(order)).sort(new FieldSortBuilder(StringConstant.ADD_TIME).order(order));
                    break;
            }

            //saas模糊查询
            boolean onlyNameLike = formDataListDTO.getShouldConditions().isEmpty();
            EsUtil.setNameLike(formDataListDTO.getSaasMark(),formDataListDTO.getNameLike(),formDataListDTO.getBusinessType(),formDataListDTO.getSimple(),boolQueryBuilder,onlyNameLike,formDataListDTO.getExplainMap(), null);
            // es脚本设置
            if (formDataListDTO.getEsScriptPojo() != null) {
                EsUtil.parseEsScript(formDataListDTO.getEsScriptPojo(), boolQueryBuilder);
            }

            //限定返回值
            List<String> fieldList = formDataListDTO.getFieldList();
            EsUtil.setFieldList(sourceBuilder, fieldList);
            //分页
            Integer page = formDataListDTO.getPage();
            Integer pageSize = formDataListDTO.getPageSize();
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            //设置查询路由
            PaasFormDataEsMappingDTO paasFormDataEsMappingDTO = new PaasFormDataEsMappingDTO();
            BeanUtil.copyProperties(formDataListDTO,paasFormDataEsMappingDTO);
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, PaasFormDataEntityExt.class);
            if (esEntities == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<PaasFormDataEntityExt> resultList = esEntities.getContent();
            //
            for (PaasFormDataEntityExt entity : resultList) {
                entity.setTagData(new JSONObject());
            }
            long num = esEntities.getTotalElements();
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount((int) num);
            paasFormDataEsListVO.setPaasFormDataESList(resultList);
            paasFormDataEsListVO.setPageHelper(pageHelper);
        } catch (XbbException e) {
            LOG.error("es查询出错",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return paasFormDataEsListVO;
    }

    @Override
    public List<PaasFormDataEntityExt> getByIdList(List<Long> idIn, String corpid, Integer saasMark, Integer businessType, List<String> fieldList, IndexTypeEnum indexTypeEnum) throws XbbException {
        return paasEsModel.getByIdList(idIn, corpid, saasMark, businessType, fieldList, indexTypeEnum);
    }

    @Override
    public List<PaasFormDataEntityExt> selectByOneCondition(Integer businessType, String attr, Object value, Map<String, Object> param, IndexTypeEnum indexTypeEnum) throws XbbException {
        return paasEsModel.selectByOneCondition(businessType, attr, value, param, indexTypeEnum);
    }

    @Override
    public List<PaasFormDataEntityExt> selectByCondition(Integer businessType, Map<String, Object> dataParam, Map<String, Object> param, IndexTypeEnum indexTypeEnum) throws XbbException {
        return paasEsModel.selectByCondition(businessType, dataParam, param, indexTypeEnum);
    }

    /**
     * 获取子表单需要查询的字段
     * @param fieldList
     * @return
     */
    private static List<String> getSubFieldList(List<String> fieldList) {
        List<String> subFieldList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(fieldList)) {
            Iterator<String> iterator = fieldList.iterator();
            while (iterator.hasNext()) {
                String item = iterator.next();
                if (item.contains(FieldTypeEnum.SUB_FORM.getEsalias())) {
                    subFieldList.add(item);
                    iterator.remove();
                }
            }
        }
        return subFieldList;
    }
}
